package com.yuke.cloud.service.uac.service.impl;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.yuke.cloud.common.base.constant.GlobalConstant;
import com.yuke.cloud.common.base.dto.LoginAuthDto;
import com.yuke.cloud.common.base.enums.ErrorCodeEnum;
import com.yuke.cloud.common.util.PublicUtil;
import com.yuke.cloud.service.api.uac.exceptions.UacBizException;
import com.yuke.cloud.service.uac.dao.AccRolePermissionMapper;
import com.yuke.cloud.service.uac.dto.RoleBindPermissionDto;
import com.yuke.cloud.service.uac.entity.*;
import com.yuke.cloud.service.uac.service.AccMenuService;
import com.yuke.cloud.service.uac.service.AccPermissionService;
import com.yuke.cloud.service.uac.service.AccRolePermissionService;
import com.yuke.cloud.common.core.support.BaseService;
import com.yuke.cloud.service.uac.service.AccRoleService;
import com.yuke.cloud.service.uac.utils.BindAuthUtil;
import com.yuke.cloud.service.uac.utils.TreeUtil;
import com.yuke.cloud.service.uac.vo.BindAuthVo;
import com.yuke.cloud.service.uac.vo.MenuVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;


/**
 * Created by wg on 2018/11/02.
 */
@Service
@Transactional
public class AccRolePermissionServiceImpl extends BaseService<AccRolePermission> implements AccRolePermissionService {
    @Resource
    private AccRolePermissionMapper accRolePermissionMapper;
    @Resource
    private AccRoleService accRoleService;
    @Resource
    private AccMenuService accMenuService;
    @Resource
    private AccPermissionService accPermissionService;

    @Override
    public int deleteByPermissionId(Long permissionId) {
        Example example = new Example(AccRolePermission.class);
        Example.Criteria criteria= example.createCriteria();
        criteria.andEqualTo("permissionId", permissionId);
        return accRolePermissionMapper.deleteByExample(example);
    }

    @Override
    public int batchDeleteByPermissionIdList(List<Long> deleteIdList) {
        logger.info("根据权限ID批量删除. deleteIdList={}", deleteIdList);
        Preconditions.checkArgument(PublicUtil.isNotEmpty(deleteIdList), "删除权限ID不能为空");
        int result = accRolePermissionMapper.batchDeleteByPermissionIdList(deleteIdList);
        if (result < deleteIdList.size()) {
//            throw new UacBizException(ErrorCodeEnum.UAC10014002, Joiner.on(GlobalConstant.Symbol.COMMA).join(deleteIdList));
        }

        return result;
    }

    @Override
    public void deleteByRoleId(Long roleId) {
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }
//        AccRolePermission rolePermission = new AccRolePermission();
//        rolePermission.setRoleId(roleId);
//        accRolePermissionMapper.delete(rolePermission);

        Example example = new Example(AccRolePermission.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("roleId", roleId);
        accRolePermissionMapper.deleteByExample(example);
    }

    @Override
    public int deleteByRoleIdList(final List<Long> roleIdList) {

        Example example = new Example(AccRolePermission.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("roleId", roleIdList);
        int result = accRolePermissionMapper.deleteByExample(example);
//        if (result < roleIdList.size()) {
//            throw new UacBizException(ErrorCodeEnum.UAC10012007, Joiner.on(GlobalConstant.Symbol.COMMA).join(roleIdList));
//        }

        return result;
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public BindAuthVo getPermissionTreeByRoleId(Long roleId) {
        BindAuthVo bindAuthVo = new BindAuthVo();
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }

        AccRole roleById = accRoleService.getRoleById(roleId);
        if (roleById == null) {
            logger.error("找不到角色信息 roleId={}", roleId);
            throw new UacBizException(ErrorCodeEnum.UAC10012005, roleId);
        }

        List<AccMenu> accMenus = accMenuService.listMenuListByRoleId(roleId);
        if (PublicUtil.isEmpty(accMenus)) {
            throw new UacBizException(ErrorCodeEnum.UAC10013009);
        }
        // 查询所有的权限信息
        List<AccPermission> accPermissions = accPermissionService.listPermissionListByMenus(accMenus);
        // 合并菜单和按钮权限 递归生成树结构

        List<MenuVo> menuVoList = BindAuthUtil.getAuthList(accMenus, accPermissions);

        List<MenuVo> tree = TreeUtil.getChildMenuVos(menuVoList, 0L);

        // 获取所有绑定的菜单和按钮权限Id集合
        List<Long> checkedAuthList = this.getCheckedPermissionList(roleId);

        // add by wg 20181222 去掉没有权限的菜单
        delNoPermissionMenu(null, tree);

        bindAuthVo.setAuthTree(tree);
        bindAuthVo.setCheckedAuthList(checkedAuthList);

        return bindAuthVo;
    }

    private void delNoPermissionMenu(MenuVo rootMenuVo, List<MenuVo> treeList) {
        for (int i = 0; i < treeList.size(); i++) {
            MenuVo menuVo = treeList.get(i);
            if (menuVo.isHasMenu()) {
                delNoPermissionMenu(menuVo, menuVo.getSubMenu());
            }

            if (!menuVo.isHasMenu()) {  // 叶子节点
                if ("menu".equals(menuVo.getDescription())) {
                    treeList.remove(menuVo);
                    i--;
                    if (PublicUtil.isEmpty(treeList)) {
                        if (rootMenuVo != null) {
                            rootMenuVo.setHasMenu(false);
                        }
                        break;
                    }
                }
            }
        }
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public List<Long> getCheckedPermissionList(Long roleId) {
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }
        return accRolePermissionMapper.getCheckedPermissionList(roleId);
    }


    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public List<AccRolePermission> listByRoleId(Long roleId) {
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }
        AccRolePermission rolePermission = new AccRolePermission();
        rolePermission.setRoleId(roleId);
        return accRolePermissionMapper.select(rolePermission);
    }


    private void insert(Long roleId, Set<Long> permissionIdList) {
        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }
        AccRolePermission accRolePermission = new AccRolePermission();
        accRolePermission.setRoleId(roleId);
        for (Long permissionId : permissionIdList) {
            accRolePermission.setRolePermissionId(super.generateId());
            accRolePermission.setPermissionId(permissionId);
            accRolePermissionMapper.insert(accRolePermission);
        }
    }

    @Override
    public void bindPermission(RoleBindPermissionDto grantAuthRole, LoginAuthDto loginAuthDto) {
        Long roleId = grantAuthRole.getRoleId();
        Set<Long> permissionIdList = grantAuthRole.getPermissionIdList();

        if (roleId == null) {
            throw new UacBizException(ErrorCodeEnum.UAC10012001);
        }

        if (Objects.equals(roleId, GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID)
                && loginAuthDto.getUserId() != GlobalConstant.Sys.SUPER_MANAGER_USER_ID) {
            logger.error("越权操作, 超级管理员用户不允许操作");
            throw new UacBizException(ErrorCodeEnum.UAC10011023);
        }

        AccRole accRole = accRoleService.getRoleById(roleId);

        if (accRole == null) {
            logger.error("找不到角色信息. roleId={}", roleId);
            throw new UacBizException(ErrorCodeEnum.UAC10012005, roleId);
        }

        // TODO 校验参数的合法性(暂时不写了, 也就是校验菜单和权限是否存在)
        List<AccRolePermission> accRolePermissionList = this.listByRoleId(roleId);

        if (PublicUtil.isNotEmpty(accRolePermissionList)) {
            this.deleteByRoleId(roleId);
        }

        if (PublicUtil.isEmpty(permissionIdList)) {
            logger.error("传入按钮权限Id为空, 取消所有按钮权限");
        } else {
            // 绑定权限
            this.insert(roleId, permissionIdList);
        }
    }

    @Override
    public List<String> getPermissionUrlListByRoleIds(List<Long> roleIdList) {
        Preconditions.checkArgument(PublicUtil.isNotEmpty(roleIdList), "权限ID不能为空");

        return accRolePermissionMapper.getPermissionUrlListByRoleIds(roleIdList);
    }
}
